package com.yixuan.mt.common.pool;

import com.yixuan.mt.common.entity.Objects;
import com.yixuan.mt.common.utitls.SnowflakeUtils;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Connection;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

@Slf4j
public class RedisPool implements EventsDestination {

    private final LinkedList<Jedis> connections = new LinkedList<>();

    private final String host;
    private final int port;
    private final String password;
    private boolean isAlive = false;

    public RedisPool(String host, int port, String password) {
        this.host = host;
        this.port = port;
        this.password = password;
        if (addConnection()) {
            this.isAlive = true;
        }
    }

    public boolean addConnection() {
        Jedis jedis;
        try {
            jedis = new Jedis(host, port);
            if (password != null) {
                jedis.auth(password);
            }
            jedis.ping();
            synchronized (connections) {
                connections.add(jedis);
            }
            return true;
        } catch (Exception e) {
            log.warn("{}{}:{}:{}", "redis://", host, port, e.getMessage());
            return false;
        }
    }

    public Jedis getConnection() {
        synchronized (connections) {
            while (connections.isEmpty()) {
                try {
                    connections.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return connections.removeFirst();
        }
    }

    public void returnConnection(Jedis connection) {
        synchronized (connections) {
            connections.add(connection);
            connections.notify();
        }
    }

    @Override
    public boolean test() {
        if (connections.isEmpty() && !addConnection()) {
            this.isAlive = false;
            return false;
        }
        Jedis connection = null;
        try {
            connection = getConnection();
            connection.ping();
            returnConnection(connection);
            this.isAlive = true;
            return true;
        } catch (Exception e) {
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ignored) {}
            }
            this.isAlive = false;
            return false;
        }
    }

    @Override
    public boolean send(Objects objects) {
        Jedis connection;
        try {
            connection = getConnection();
            String key = "mt:" + SnowflakeUtils.nextId();
            Map<String, String> map = new HashMap<>();
            map.put("name", objects.getName());
            map.put("parentPath", objects.getParentPath());
            map.put("type", objects.getType());
            map.put("size", String.valueOf(objects.getSize()));
            connection.hmset(key, map);
            returnConnection(connection);
            return true;
        } catch (Exception e) {
            log.error("Send event fail {}:{}", host, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean isAlive() {
        return this.isAlive;
    }
}
